package br.uff.probabilidade.modelo.tabuleiro;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Vector;

import javax.swing.JOptionPane;

import br.uff.probabilidade.applet.Atividade;
import br.uff.probabilidade.applet.Tabuleiro;
import br.uff.probabilidade.modelo.Evento;
import br.uff.probabilidade.modelo.Imagem;
import br.uff.probabilidade.modelo.Marcador;
import br.uff.probabilidade.modelo.Operacao;
import br.uff.probabilidade.modelo.Quadrado;

public class Nivel {
	public static final int FORMATO_EXPRESSAO = 0; //Exibir problema em forma de expressao
	public static final int FORMATO_DESCRICAO = 1; //Exibir problema em forma descritiva
	
	private Vector eventos = new Vector();
	private Vector operacoes = new Vector();	
	private Vector quadrados = new Vector();
	private Vector probabilidades = new Vector();
	
	protected static final char[] NOMES_EVENTO={'A','B','C','D','E','F','G','H'};
	protected static final Color [] COLORS={new Color(222,222,246),new Color(200,200,246),new Color(170,170,246),new Color(193,240,240)};
	
	private int numColunas=6,numLinhas=6;
	
	private String mensagemInicial="";
	
	private boolean complemento = false;	
	
	private boolean perguntaExpressao = false;
	
	private boolean probabilidadeOperacao = false;
	
	private int formato = FORMATO_DESCRICAO;
	
	private boolean ativo=false;
	private Atividade atividade;
	
	private Nivel herdado = null;
	
	public boolean hasComplemento(){
		return this.complemento;
	}
	
	public void setHasComplemento(boolean complemento){
		this.complemento = complemento;
	}
	
	public Nivel(Atividade atividade){
		this.atividade = atividade;		
	}
	
	public Nivel(Atividade atividade,Nivel herdado){
		this.atividade = atividade;		
		this.herdado = herdado;
	}
	
	public void addHeranca(Nivel herdado){		
		this.herdado = herdado;		
	}
	
	private void aplicaHeranca(){
		if(this.herdado!=null){
			this.eventos.removeAllElements();
			for(int i=0;i<herdado.qntEventos();i++){
				this.addEvento(herdado.getEventoAt(i));
			}
			
			this.operacoes.removeAllElements();
			
			for(int i=0;i<herdado.qntOperacoes();i++){
				this.addOperacao(herdado.getOperacaoAt(i));
			}
		}
	}
	
	private boolean isEventoHerdado(Evento evento){		
		if(this.herdado!=null){
			for(int i=0;i<herdado.qntEventos();i++){
				if(this.herdado.getEventoAt(i).getLegenda().getDescricao().equals(evento.getLegenda().getDescricao()))
					return true;
			}
			
			for(int i=0;i<herdado.qntOperacoes();i++){
				if(this.herdado.getOperacaoAt(i).getLegenda().getDescricao().equals(evento.getLegenda().getDescricao()))
					return true;
			}
		}
		return false;
	}
	
	public void monta(Imagem check){
		this.aplicaHeranca();
		if(this.isProbabilidadeOperacao()){
			this.addProbabilidadeOperacoes();
		}
		this.setAtivo(true);
		int posicao= -1;
		String buscarPor,nova;
		for(int i=0;i<this.qntEventos();i++){
			this.getEventoAt(i).getConjunto().setNome(this.NOMES_EVENTO[i]);
			for(int j=0;j<qntOperacoes();j++){				
				buscarPor = "'"+this.getEventoAt(i).getLegenda().getDescricao()+"'";
				posicao = this.getOperacaoAt(j).getExpressao().indexOf(buscarPor);				
				if(posicao!=-1){					
					nova = this.getOperacaoAt(j).getExpressao().replace(buscarPor,String.valueOf(this.getEventoAt(i).getConjunto().getNome()));					
					this.getOperacaoAt(j).setExpressao(nova);
				}
			}
		}
		for(int i=0;i<6;i++)
			for(int j=0;j<6;j++)
				this.criaQuadradoAt(i, j,check);	
		
		int count = 0;
		for(int i=0;i<qntQuadrados();i++){
			count=0;
			for(int j=0;j<getQuadrado(i).qntMarcadores();j++){
				if(!(getQuadrado(i).getMarcador(j).getEvento() instanceof Operacao)){
					getQuadrado(i).getMarcador(j).getEvento().getLegenda().setCor(COLORS[count]);
					count++;
				}else
					getQuadrado(i).getMarcador(j).getEvento().getLegenda().setCor(COLORS[COLORS.length-1]);
			}
		}
	}
	
	public Quadrado getQuadrado(int index){
    	if(quadrados.get(index)!=null){
    		return (Quadrado)this.quadrados.get(index);
    	}
    	return null;
    }
	
	public int setMostrandoErros(){
		int qntErro = 0;
		for(int i=0;i<qntQuadrados();i++){
			for(int j=0;j<getQuadrado(i).qntMarcadores();j++){
				if(!getQuadrado(i).getMarcador(j).isAceito()){
					getQuadrado(i).getMarcador(j).setMostrandoErro(true);
					qntErro++;
				}else
					getQuadrado(i).getMarcador(j).setMostrandoErro(false);
			}
		}
		return qntErro;
	}
    
    public Quadrado getQuadrado(int linha,int coluna){
    	int i = linha*numColunas + coluna;
    	return this.getQuadrado(i);
    }
    
    public Evento existeEvento(Evento evento){
    	for(int i=0;i<this.eventos.size();i++){
    		if(this.getEventoAt(i).getLegenda().getDescricao().equals(evento.getLegenda().getDescricao()))
    			return this.getEventoAt(i);
    	}
    	return null;
    }
	
	public char addEvento(Evento evento){
		Evento buscado = existeEvento(evento); 
		if(buscado==null){			
			this.eventos.add(evento);		
			return this.getEventoAt(this.eventos.size()-1).getConjunto().getNome();
		}
		return buscado.getConjunto().getNome();
	}
	
	public void addEventoAgrupado(Evento evento){
		addEvento(evento);		
	}
	
	public void addOperacao(Operacao operacao){
		for(int i=0;i<qntOperacoes();i++)
			if(getOperacaoAt(i).getLegenda().getDescricao().equals(operacao.getLegenda().getDescricao()))return;
		this.operacoes.add(operacao);
	}	
	
	public Probabilidade getProbabilidadeAt(int i){
		return (Probabilidade)this.probabilidades.get(i);
	}
	
	public void addProbabilidade(Probabilidade probabilidade){		
		this.probabilidades.add(probabilidade);
	}	
	
	public Evento getEventoAt(int i){
		return (Evento)this.eventos.get(i);
	}
	
	public Operacao getOperacaoAt(int i){
		return (Operacao)this.operacoes.get(i);
	}
	
	private void criaQuadradoAt(int x,int y,Imagem check){
    	this.criaQuadradoAt(new Point(x,y),check);
    }
    
    private void criaQuadradoAt(Point coordenadas,Imagem check){    	
    	Quadrado quadrado = new Quadrado(coordenadas,this.coordenadas2Posicao(coordenadas),Tabuleiro.ESPACO_COLUNAS,Tabuleiro.ESPACO_LINHAS,this.criaMarcadores(check));
    	for(int i=0;i<quadrado.qntMarcadores();i++){
    	//	if(!(quadrado.getMarcador(i).getEvento() instanceof Operacao))
    			if(quadrado.getMarcador(i).getEvento().isValido(coordenadas) && this.isEventoHerdado(quadrado.getMarcador(i).getEvento()))
    				quadrado.getMarcador(i).setMarcado(true);
    	}
		this.quadrados.add(quadrado);
    }
    
    private void desenhaQuadrados(Graphics g){
    	for(int i=0;i<this.quadrados.size();i++)
    		this.getQuadrado(i).desenha(g);
    }       
    
    public void desenha(Graphics g){
    	this.desenhaQuadrados(g);
    }
    
    
    
    private Point coordenadas2Posicao(int x,int y){
    	return coordenadas2Posicao(new Point(x,y));
    }
    
    private Point coordenadas2Posicao(Point coordenadas){
    	return new Point(this.atividade.getPosicao().x+(Tabuleiro.ESPACO_COLUNAS*((coordenadas.x))),this.atividade.getPosicao().y+(Tabuleiro.ESPACO_LINHAS*((coordenadas.y))));
    }
	
	private Vector criaMarcadores(Imagem check){
    	Vector marcadores = new Vector();
    	    	    	
    	for(int i=0;i<this.eventos.size();i++){    		
    		marcadores.add(new Marcador(Marcador.DEFAULT_WIDTH,Marcador.DEFAULT_HEIGHT,this.getEventoAt(i),check));
    	}
    	
    	for(int i=0;i<this.operacoes.size();i++){    		
    		marcadores.add(new Marcador(Marcador.DEFAULT_WIDTH,Marcador.DEFAULT_HEIGHT,this.getOperacaoAt(i),check));
    	}
    	
    	
    	return marcadores;
    }
	
	public boolean isCompleto(){
		boolean completo = true;
    	Quadrado quadrado;
    	for(int i=0;i<this.probabilidades.size();i++){
    		if(!this.getProbabilidadeAt(i).isCorreto())
    			completo = false;
    	}    	
    	
    	if(this.perguntaExpressao){
    		for(int i=0;i<this.qntOperacoes();i++){
    			if(!this.getOperacaoAt(i).isExpressaoCorreta()){
    				completo=false;
    			}
    		}
    	}
		if(completo){
    		for(int i=0;i< numLinhas;i++){
    			for(int j=0;j<numColunas;j++){
    				quadrado = this.getQuadrado(i, j);
    				for(int k=0;k<quadrado.qntMarcadores();k++){
    					if((quadrado.getMarcador(k).getEvento().isValido(quadrado.getCoordenadas()) && !quadrado.getMarcador(k).isMarcado())
    							|| (!quadrado.getMarcador(k).getEvento().isValido(quadrado.getCoordenadas()) && quadrado.getMarcador(k).isMarcado())){
    						
    						if(quadrado.getMarcador(k).isMarcado()){
    							quadrado.getMarcador(k).getEvento().getConjunto().getParByValue(quadrado.getCoordenadas()).setAceito(false);
    							quadrado.getMarcador(k).setAceito(false);
    						}
    						
    						completo = false;
    					}else
    						quadrado.getMarcador(k).setAceito(true);
    				}
    			}
    		}
		}
		return completo;
	}
	
	private void addProbabilidadeOperacaoHeranca(boolean complemento){
		if(this.herdado==null)return;
		Probabilidade probabilidade;		
		for(int i=0;i<herdado.qntEventos();i++){
			if(complemento){
				probabilidade = new Probabilidade(herdado.getOperacaoAt(i),true);
				this.addProbabilidade(probabilidade);
			}
			probabilidade = new Probabilidade(herdado.getOperacaoAt(i));
			this.addProbabilidade(probabilidade);
		}
	}
	
	private void addProbabilidadeEventoHeranca(boolean complemento){
		if(this.herdado==null)return;
		Probabilidade probabilidade;		
		for(int i=0;i<herdado.qntEventos();i++){
			if(complemento){
				probabilidade = new Probabilidade(herdado.getEventoAt(i),true);
				this.addProbabilidade(probabilidade);
			}
			probabilidade = new Probabilidade(herdado.getEventoAt(i));
			this.addProbabilidade(probabilidade);
		}
	}
	
	public void addProbabilidadeEventos(boolean complemento){
		Probabilidade probabilidade;		
		for(int i=0;i<qntEventos();i++){
			if(complemento){
				probabilidade = new Probabilidade(this.getEventoAt(i),true);
				this.addProbabilidade(probabilidade);
			}
			probabilidade = new Probabilidade(this.getEventoAt(i));
			this.addProbabilidade(probabilidade);
		}
		this.addProbabilidadeEventoHeranca(complemento);
	}
	
	private void addProbabilidadeOperacoes(){
		Probabilidade probabilidade;
		for(int i=0;i<qntOperacoes();i++){
			probabilidade = new Probabilidade(this.getOperacaoAt(i));
			this.addProbabilidade(probabilidade);
		}
		//this.addProbabilidadeOperacaoHeranca(complemento);
	}

	public boolean isAtivo() {
		return ativo;
	}

	public void setAtivo(boolean ativo) {
		this.ativo = ativo;
	}
	
	public int qntQuadrados(){
		return this.quadrados.size();
	}
	
	public int qntEventos(){
		return this.eventos.size();
	}
	
	public int qntOperacoes(){
		return this.operacoes.size();
	}
	
	public int qntProbabilidades(){
		return this.probabilidades.size();
	}
	

	public String getMensagemInicial() {
		return mensagemInicial;
	}

	public void setMensagemInicial(String msg) {
		this.mensagemInicial = msg;
	}

	public int getFormato() {
		return formato;
	}

	public void setFormato(int formato) {
		this.formato = formato;
	}

	public boolean isPerguntaExpressao() {
		return perguntaExpressao;
	}

	public void setPerguntaExpressao(boolean perguntaExpressao) {
		this.perguntaExpressao = perguntaExpressao;
	}

	public boolean isProbabilidadeOperacao() {
		return probabilidadeOperacao;
	}

	public void setProbabilidadeOperacao(boolean probabilidadeOperacao) {
		this.probabilidadeOperacao = probabilidadeOperacao;
	}

}
